import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

/** Questa e' la classe principale che gestisce la faccia
*  
* @author Simoncelli Davide && Beschi Jacopo
* @version 1.0
*/

public class Primo extends Applet implements Runnable, MouseMotionListener {

       private static final long serialVersionUID = 1195087343242523235L;

       /**
        * Coordinate cartesiane che identificano la posizione della faccia
        */
       
       private int x,y;

       /**
        * Oggetto Image su cui disegnare
        */
       
       private Image offScreenImage;
       
       /**
        * Oggetti Pupilla destra e sinistra
        */
       
       private Pupilla pupSx, pupDx;
       
       /**
        * Oggetto Bocca
        */
       
       private Bocca bocca;
       
       /**
        * Costante per definire la larghezza della faccia
        */
       
       static final int hFaccia = 250;
       
       /**
        * Costante per definire la lunghezza della faccia
        */
       
       static final int wFaccia = 300;
       
       /**
        * Costante per definire la larghezza della bocca
        */
       
       static final int larghezzaBocca = 40;
       
       /**
        * Costante per definire la lunghezza della bocca
        */
       
       static final int lunghezzaBocca = 150;
       
       /**
        * Costante per definire la Larghezza e lunghezza dell'occhio
        */
       
       static final int wOcchio=100, hOcchio=140;
       
       /**
        * Coordinata x Occhio sinistro
        */
       int xOcchioSx;
       
       /**
        *Coordinata y Occhio sinistro
        */
       int yOcchioSx;
       
       /**
        * Coordinata x Occhio Destro
        */
       int xOcchioDx;
       
       /**
        * Coordinate y Occhio Destro
        */
       int yOcchioDx;
       
       /**
        * Constante per il colore della faccia
        */
       
       static final Color coloreFaccia = new Color(176,108,73);
       
       /**
        * Constante per il colore degli occhi
        */
       
       static final Color coloreOcchi = Color.WHITE;
       
       /**
        * Constante per il colore dei contorni delle figure
        */
       
       static final Color coloreContorni = Color.BLACK;
       
       /**
        * Constante per il colore della pupilla
        */
       
       static final Color colorePupilla = new Color(64,200,71);
       
       /**
        * Constante per il colore della bocca
        */
       
       static final Color coloreBocca = new Color(241,19,19);
       
       /**
        *  Coordinate x e y delle dei due oggetti Pupille centrate negli occhi
        */
       
       int xPupSx, yPupSx;
       
       int xPupDx, yPupDx;
       
       /**
        * Diametro delle due pupille
        */
       
       static final int diametroPupilla=30;
       
       
       private Mosca mosca;
       
       private Thread t;
       
       /**
        * Metodo per inizializzare l'applet
        */
       
       public void init()
       {
               x = 110;
               y = 280;
         
               mosca = new Mosca(this);
               t = new Thread(this);
               t.start();
               // assegno le posizioni dei vari oggetti in dipendenza alla faccia
               int offsetX=wFaccia/2-lunghezzaBocca/2;
               int offsetY=hFaccia/2+larghezzaBocca*3/2;
               /* Creo l'oggetto Bocca */
               bocca = new Bocca(x,y,offsetX,offsetY);
                               
               // calcolo offset per posizionare la pupilla
               xOcchioSx=x+wFaccia/2-wOcchio/2-wFaccia/5;
               yOcchioSx=y+hFaccia/6;
               xOcchioDx=x+wFaccia/2-wOcchio/2+wFaccia/5;
               yOcchioDx=yOcchioSx;
               xPupSx=xOcchioSx+wOcchio/2-diametroPupilla/2;
               yPupSx=yOcchioSx+hOcchio/2-diametroPupilla/2;
               xPupDx=xOcchioDx+wOcchio/2-diametroPupilla/2;
               yPupDx=yOcchioDx+hOcchio/2-diametroPupilla/2;
               
               // creo gli oggetti pupilla e bocca
               pupSx = new Pupilla(xPupSx,yPupSx,diametroPupilla);
               pupDx = new Pupilla(xPupDx,yPupDx,diametroPupilla);
               move();
               // crea i listener per gli eventi
               addMouseMotionListener(this);
       }
       
       private void  move() {
               xOcchioSx=x+wFaccia/2-wOcchio/2-wFaccia/5;
               yOcchioSx=y+hFaccia/6;
               xOcchioDx=x+wFaccia/2-wOcchio/2+wFaccia/5;
               yOcchioDx=yOcchioSx;
               xPupSx=xOcchioSx+wOcchio/2-diametroPupilla/2;
               yPupSx=yOcchioSx+hOcchio/2-diametroPupilla/2;
               xPupDx=xOcchioDx+wOcchio/2-diametroPupilla/2;
               yPupDx=yOcchioDx+hOcchio/2-diametroPupilla/2;
               bocca.sposta(x, y);
               pupDx.setX(xPupDx);
               pupSx.setX(xPupSx);
               pupDx.setY(yPupDx);
               pupSx.setY(yPupSx);
               
       }
       
       public void run() {
               while(true) {
                       try {
                               t.sleep(100);
                       }
                       catch(InterruptedException e) { System.out.println("Eccezzione: "+e); }
                       repaint();
               }
       }
       
       /**
        * Avvia l'applet
        */
       
       public void start()
       {
               if(offScreenImage == null)
                       offScreenImage = createImage(getSize().width,getSize().height);
       }


       public void update(Graphics g)
       {
               if(offScreenImage != null)
               {
                       Graphics offScreenGraphics = offScreenImage.getGraphics();
                       /* Imposta il colore  finestra */
                       offScreenGraphics.setColor(getBackground());
                       /* Cancella la parte vecchia disegnando un rettangolo dello stesso colore della finestra */
                       offScreenGraphics.fillRect(0, 0 ,getSize().width, getSize().height);
                       /* Ripristina il colore precedente */
                       offScreenGraphics.setColor(g.getColor());
                       /* Disegna sul offScreenGraphics invece che sulla finestra */
                       paint(offScreenGraphics);
                       /* Disegna sulla finestra */
                       g.drawImage(offScreenImage, 0, 0, this);

               }
       }
       
       /**
        * Disegna sullo schermo la faccia con occhi, bocca e pupille
        */
       
       public void paint(Graphics g)
       {
               /* Riaggiorna le coordinate delle varie parti della faccia */
               move();
               
               /* Disegna la faccia */
               Graphics2D g2 = (Graphics2D) g;
               
               g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
               g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
               
               g2.setColor(coloreFaccia);
               g2.fillOval(x, y, wFaccia, hFaccia);
               g2.setColor(Color.BLACK);
               g2.drawOval(x, y, wFaccia, hFaccia);

               /* Disegna gli occhi */
               g2.setColor(coloreOcchi);
               g2.fillOval(xOcchioSx, yOcchioSx, wOcchio, hOcchio);
               g2.fillOval(xOcchioDx, yOcchioDx, wOcchio, hOcchio);

               /* Disegna il contorno degli occhi */
               g2.setColor(coloreContorni);
               g2.drawOval(xOcchioSx, yOcchioSx, wOcchio, hOcchio);
               g2.drawOval(xOcchioDx, yOcchioDx, wOcchio, hOcchio);
               
               g.drawArc(x+40,y-20,10,80,30,180);
               g.drawArc(x+80,y-45,10,80,30,180);
               g.drawArc(x+110,y-55,10,80,30,180);
               g.drawArc(x+140,y-57,10,80,30,180);
               g.drawArc(x+170,y-60,10,80,30,180);
               g.drawArc(x+200,y-55,10,80,30,180);
               g.drawArc(x+230,y-40,10,80,30,180);
               g.drawArc(x+260,y-20,10,80,30,180);
               
               /* Disegna le soppracciglia */
               g2.drawArc(xOcchioDx+5, yOcchioDx-10, 80,30, 15,150);
               g2.drawArc(xOcchioSx+5, yOcchioSx-10, 80,30, 15,150);
               
               /* Disegna la bocca */
               bocca.paint(g2);

               /* Disegna le pupille */
               pupSx.paint(g2);
               pupDx.paint(g2);
               
               mosca.disegna(g2);
              
               pupSx.seguiMouse((int)mosca.getX(),(int)mosca.getY());
               pupDx.seguiMouse((int)mosca.getX(), (int)mosca.getY());
            
       }
       
       /**
        * Variabile incremento che gestisce lo spostamento delle pupille
        */
       
       int incremento = 10;
       
       /**
        * Sposta le pupille in modo alternato se viene cliccato un pulsante del mouse
        */
       
       public void mouseClicked(MouseEvent e) {

       }

       public void mouseEntered(MouseEvent e) {
       }

       public void mouseExited(MouseEvent e) {

       }

       public void mousePressed(MouseEvent e) {
       }
       
       public void mouseReleased(MouseEvent e) {
       }
       
       /**
        * Questo metodo permette di spostare la pupilla seguendo il mouse quando uno dei tasti è premuto
        * @param e oggetto MouseEvent per gestire l'evento mouse
        */
       
       public void mouseDragged(MouseEvent e) {
    	   int xCFaccia = x+wFaccia/2;
    	   int yCFaccia = y+hFaccia/2;
    	   double a = Math.pow(wFaccia/2,2);
    	   double b = Math.pow(hFaccia/2,2);
           //if(Math.abs(e.getX() - x-wFaccia/2) < 210 && Math.abs(e.getY() - y-wFaccia/2) < 210) {
    	   if(Math.pow(e.getX()-xCFaccia,2)/a+Math.pow(e.getY()-yCFaccia,2)/b <= 1)
    	   {
    		   x = e.getX() - wFaccia/2;
    		   y = e.getY() - hFaccia/2;
    		   xCFaccia = x+wFaccia/2;
        	   yCFaccia = y+hFaccia/2;
    	   }
       }

       /**
        * Questo metodo permette di spostare la pupilla seguendo il mouse
        * @param e oggetto MouseEvent per gestire l'evento mouse
        */
       
       public void mouseMoved(MouseEvent e) {
       }
       
} //class
